﻿using Greet;
using Grpc.Core;
using MyGrpcService.Services;

namespace MyGrpcService
{
    public class TaskInfo
    {
        private Task _tk = null;
        private bool _isStarted = false;

        private GrpcData _request = null;
        private IServerStreamWriter<GrpcData> _writerStream = null;
        private ServerCallContext _context = null;
        private QueueInfo<GrpcData> _resDataQueue = null;
        private CancellationTokenSource _cacelTokenSource = new CancellationTokenSource();

        public TaskInfo(GrpcData request, IServerStreamWriter<GrpcData> responseStream, ServerCallContext context, QueueInfo<GrpcData> resDataQueue)
        {
            _request = request;
            _writerStream = responseStream;
            _context = context;
            _resDataQueue = resDataQueue;
        }

        public bool IsStarted
        {
            get
            {
                if (_tk == null)
                {
                    _isStarted = false;
                }
                else if (_tk.IsCompleted)
                {
                    _isStarted = false;
                    _tk.Dispose();
                    _tk = null;
                }
                else
                {
                    _isStarted = true;
                }
                return _isStarted;
            }
        }

        public Task GetTask()
        {
            return _tk;
        }
        public bool Start()
        {
            try
            {
                if (IsStarted)
                {
                    return true;
                }
                _isStarted = true;
                _tk = Task.Factory.StartNew(DataWriteThead);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        public bool Stop()
        {
            try
            {
                if (IsStarted)
                {
                    _isStarted = false;
                    if (_resDataQueue == null)
                    {
                        return false;
                    }
                    //_resDataQueue.QueueResetEvent.Set();
                }
                _isStarted = false;
                _cacelTokenSource.Cancel();
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        private void DataWriteThead()
        {
            if (_writerStream == null || _request == null || _context == null || _resDataQueue == null)
            {
                return;
            }
            while (_isStarted && !_context.CancellationToken.IsCancellationRequested && !_cacelTokenSource.IsCancellationRequested)
            {
                try
                {
                    //if (_resDataQueue.IsEmpty)
                    //{
                    //    _resDataQueue.QueueResetEvent.WaitOne();
                    //}
                    //GrpcData data;
                    //if (_resDataQueue.TryPeek(out data))
                    //{
                    //    // 向客户端发送数据
                    //    Task wTask = _writerStream.WriteAsync(data);
                    //    wTask.Wait(5000, _cacelTokenSource.Token);
                    //    if (!wTask.IsCanceled && !wTask.IsFaulted)
                    //    {
                    //        _resDataQueue.TryDequeue(out data);
                    //    }
                    //}
                }
                catch (Exception ex)
                {

                }
            }
        }


        private Grpc.Core.Server _pServer = null;
        CorrespondGrpcServiceServer csServer = null;
        public bool Start()
        {
            try
            {
                if (_pServer == null)
                {
                    csServer = new CorrespondGrpcServiceServer();
                    csServer.MessageHandler = ServerReceiveData;
                    _pServer = new Grpc.Core.Server
                    {
                        Services = { CorrespondGrpcService.BindService(csServer) },
                        Ports = { new ServerPort(IP, Port, ServerCredentials.Insecure) }
                    };
                    _pServer.Start();
                }

                IsStarted = true;
                return IsStarted;

            }
            catch (Exception ex)
            {
                return false;
            }
        }
        public bool Stop()
        {
            try
            {
                if (!IsStarted)
                {
                    return true;
                }
                if (_pServer != null)
                {
                    _pServer.ShutdownAsync();
                    _pServer = null;
                }
                IsStarted = false;
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        //服务端向客户端发送消息，把消息加入队列进行处理
        public bool SendMsg(string ip, int port, GrpcData msg)
        {
            string strKey = GetKeyStr(ip.Trim(), port);
            TaskInfo tk = null;
            if (csServer._receiveDataTaskId.ContainsKey(strKey))
            {
                tk = csServer._receiveDataTaskId[strKey];
                if (tk == null || !tk.IsStarted)
                {
                    return false;
                }
                DataQueues.SendDataQueue[IpPortStrKey].Enqueue(msg);
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 收到client调用SendMsg传来的数据，Grpc的Server可以直接响应返回，不需要再给指定Ip端口发送返回数据
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private GrpcResult ServerReceiveData(GrpcData data)
        {
            Task tk = new Task(() => { ProcessData(data, data.Ip, data.Port); });
            tk.Start();
            return new GrpcResult() { Result = true };
        }
    }
}
